#include "CVideoDriver.h"
#include "Math.h"
#include "cResourceManager.h"
CVideoDriver::CVideoDriver()
{
	m_iFBOProgram=0;
	m_iFBOColor=0;
	m_iFBODepth=0;
}
CVideoDriver::~CVideoDriver(){}
CVideoDriver* CVideoDriver::s_Instance = 0;
CVideoDriver* CVideoDriver::GetInstance()
{
	if(!s_Instance)
	{
		s_Instance =  new CVideoDriver();
	}
	return s_Instance;
}

void CVideoDriver::DestroyInstance()
{
	SAFE_DEL(s_Instance);
}
void CVideoDriver::SetFBO(int index)
{
	if (!m_iFBOProgram)
        glGenFramebuffers (1, &m_iFBOProgram);

    if (!m_iFBOColor[index])
    {
        glGenTextures(1, &m_iFBOColor[index]);
        glBindTexture(GL_TEXTURE_2D, m_iFBOColor[index]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  SCREEN_W, SCREEN_H, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }

    if (!m_iFBODepth[index])
    {
        glGenTextures(1, &m_iFBODepth[index]);
        glBindTexture(GL_TEXTURE_2D, m_iFBODepth[index]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SCREEN_W, SCREEN_H, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);

        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }

    glBindFramebuffer(GL_FRAMEBUFFER, m_iFBOProgram);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_iFBOColor[index], 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_iFBODepth[index], 0);
   
    int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE)
		cout<<"Could not create FBO buffer\n";

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
}
void CVideoDriver::StopFBO()
{
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

GLuint CVideoDriver::getiFBOProgram() const
{
	return m_iFBOProgram;
}
GLfloat m_aVertices[]={-1.0f,-1.0f,-1.0f,1.0f,1.0f,-1.0f,1.0f,1.0f};
void CVideoDriver::DrawNomal(GLuint colorBuffer)
{
	static GLint program;
	char *v_shader= cResourceManager::GetInstance()->getUrl_vShader(12);
	char *f_shader= cResourceManager::GetInstance()->getUrl_fShader(12);
	program=esLoadProgram(esLoadShader(GL_VERTEX_SHADER, v_shader),esLoadShader(GL_FRAGMENT_SHADER, f_shader));
	
	
	glUseProgram(program);
	GLint positionAttribute = glGetAttribLocation(program, "a_posL");
	GLint textureUniform = glGetUniformLocation(program, "u_texture");

		if(positionAttribute != -1)
		{
			glEnableVertexAttribArray(positionAttribute);
			glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE, 0, m_aVertices);
		}

		if (textureUniform != -1)
		{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, colorBuffer);
		glUniform1i(textureUniform, 0);
		}

	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void CVideoDriver::Drawblur(GLuint colorBuffer)
{
	static GLint program;
	char *v_shader= cResourceManager::GetInstance()->getUrl_vShader(13);
	char *f_shader= cResourceManager::GetInstance()->getUrl_fShader(13);
	program=esLoadProgram(esLoadShader(GL_VERTEX_SHADER, v_shader),esLoadShader(GL_FRAGMENT_SHADER, f_shader));
	
	
	glUseProgram(program);
	GLint positionAttribute = glGetAttribLocation(program, "a_posL");
	GLint textureUniform = glGetUniformLocation(program, "u_texture");
	GLint step = glGetUniformLocation(program, "step");
		if(positionAttribute != -1)
		{
			glEnableVertexAttribArray(positionAttribute);
			glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE, 0, m_aVertices);
		}

		if (textureUniform != -1)
		{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, colorBuffer);
		glUniform1i(textureUniform, 0);
		}
		if(step!=-1)
		{
			int k=5;
		float x = 1.0f/SCREEN_W;
		float y = 1.0f/SCREEN_H;
		float z = sqrt(2.0f) / 2.0f * x;
		float w = sqrt(2.0f) / 2.0f * y;
		glUniform4f(step,k*x, k*y, k*z, k*w);
		}
		SAFE_DEL_ARRAY(v_shader);
		SAFE_DEL_ARRAY(f_shader);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void CVideoDriver::DrawBlackWhite(GLuint colorBuffer)
{
	static GLint program;
	char *v_shader= cResourceManager::GetInstance()->getUrl_vShader(14);
	char *f_shader= cResourceManager::GetInstance()->getUrl_fShader(14);
	program=esLoadProgram(esLoadShader(GL_VERTEX_SHADER, v_shader),esLoadShader(GL_FRAGMENT_SHADER, f_shader));
	
	
	glUseProgram(program);
	GLint positionAttribute = glGetAttribLocation(program, "a_posL");
	GLint textureUniform = glGetUniformLocation(program, "u_texture");
		if(positionAttribute != -1)
		{
			glEnableVertexAttribArray(positionAttribute);
			glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE, 0, m_aVertices);
		}

		if (textureUniform != -1)
		{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, colorBuffer);
		glUniform1i(textureUniform, 0);
		}
		
		SAFE_DEL_ARRAY(v_shader);
		SAFE_DEL_ARRAY(f_shader);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void CVideoDriver::DrawBloom(GLuint colorBuffer)
{
	static GLint program;
	char *v_shader= cResourceManager::GetInstance()->getUrl_vShader(15);
	char *f_shader= cResourceManager::GetInstance()->getUrl_fShader(15);
	program=esLoadProgram(esLoadShader(GL_VERTEX_SHADER, v_shader),esLoadShader(GL_FRAGMENT_SHADER, f_shader));
	
	
	glUseProgram(program);
	GLint positionAttribute = glGetAttribLocation(program, "a_posL");
	GLint textureUniform = glGetUniformLocation(program, "u_texture");


		if(positionAttribute != -1)
		{
			glEnableVertexAttribArray(positionAttribute);
			glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE, 0, m_aVertices);
		}

		if (textureUniform != -1)
		{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, colorBuffer);
		glUniform1i(textureUniform, 0);
		}
	
		SAFE_DEL_ARRAY(v_shader);
		SAFE_DEL_ARRAY(f_shader);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void CVideoDriver::DrawBloompro(GLuint colorBuffer)
{
	static GLint program;
	char *v_shader= cResourceManager::GetInstance()->getUrl_vShader(16);
	char *f_shader= cResourceManager::GetInstance()->getUrl_fShader(16);
	program=esLoadProgram(esLoadShader(GL_VERTEX_SHADER, v_shader),esLoadShader(GL_FRAGMENT_SHADER, f_shader));
	glUseProgram(program);
	GLint positionAttribute = glGetAttribLocation(program, "a_posL");
	GLint textureUniform = glGetUniformLocation(program, "u_texture");
	GLint depthTex = glGetUniformLocation(program, "depthTex");

		if(positionAttribute != -1)
		{
			glEnableVertexAttribArray(positionAttribute);
			glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE, 0, m_aVertices);
		}

		if (textureUniform != -1)
		{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, colorBuffer);
		glUniform1i(textureUniform, 0);
		}
		if (depthTex != -1)
		{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, colorBuffer);
		glUniform1i(depthTex, 0);
		}
		SAFE_DEL_ARRAY(v_shader);
		SAFE_DEL_ARRAY(f_shader);
		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}